package com.ruoyi.common.utils;

import com.ruoyi.common.utils.modbus.TcpToSerialClient;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class FrameBuilder {

    // 帧头结构定义
    private static final int FRAME_HEADER_LENGTH = 6;
    private static final int LENGTH_OFFSET = 4; // 第5-6字节存储数据长度（高位在前）
    private static final byte[] HEADER_PREFIX = {0x00, 0x00, 0x00, 0x00};

    /**
     * 构建完整数据帧
     *
     * @param data    字符串数据
     * @param addCrLf 是否添加回车换行符(\r\n)
     * @return 完整帧字节数组（帧头+数据段）
     */
    public static byte[] buildFrame(String data, boolean addCrLf) {
        // 处理数据，添加回车换行符（预期结果包含0D 0A）
        String processedData = addCrLf ? data + "\r\n" : data;
        byte[] dataBytes = processedData.getBytes(StandardCharsets.UTF_8);
        int dataLength = dataBytes.length;

        if (dataLength > 0xFFFF) {
            throw new IllegalArgumentException("数据长度超过最大限制(65535字节)");
        }

        // 创建帧头
        byte[] header = new byte[FRAME_HEADER_LENGTH];
        System.arraycopy(HEADER_PREFIX, 0, header, 0, Math.min(HEADER_PREFIX.length, 4));

        // 设置数据长度（高位在前，低位在后）
        header[LENGTH_OFFSET] = (byte) ((dataLength >> 8) & 0xFF); // 高位字节
        header[LENGTH_OFFSET + 1] = (byte) (dataLength & 0xFF);     // 低位字节

        // 合并帧头和数据
        byte[] fullFrame = new byte[FRAME_HEADER_LENGTH + dataLength];
        System.arraycopy(header, 0, fullFrame, 0, FRAME_HEADER_LENGTH);
        System.arraycopy(dataBytes, 0, fullFrame, FRAME_HEADER_LENGTH, dataLength);
        return fullFrame;
    }

    /**
     * 解析数据帧（同步支持高位在前的长度字段）
     *
     * @param frame 完整帧数据
     */
    public static void parseFrame(byte[] frame) {
        if (frame.length < FRAME_HEADER_LENGTH) {
            throw new IllegalArgumentException("帧长度不足");
        }

        // 解析长度字段（高位在前）
        int length = (frame[LENGTH_OFFSET] & 0xFF) << 8 | (frame[LENGTH_OFFSET + 1] & 0xFF);

        // 验证帧长度
        int expectedLength = FRAME_HEADER_LENGTH + length;
        if (frame.length != expectedLength) {
            throw new IllegalArgumentException("帧长度与声明不符: 实际=" + frame.length + ", 预期=" + expectedLength);
        }

        // 提取并转换数据
        byte[] dataSegment = Arrays.copyOfRange(frame, FRAME_HEADER_LENGTH, frame.length);
        String data = new String(dataSegment, StandardCharsets.UTF_8);
        System.out.println("解析结果: " + data);
    }

//    public static void main(String[] args) {
//        byte[] headerPrefix = {0x00, 0x00, 0x00, 0x00};
//        String testData = "$HXDQ,1,1,0,0,0,0,0,*35";
//
//        // 构建帧（添加回车换行符，长度字段高位在前）
//        byte[] frame = buildFrame(headerPrefix, testData, true);
//
//        System.out.println("生成的帧: " + bytesToHex(frame));
//        parseFrame(frame);
//    }

    public static void main(String[] args) {
        // 1. 配置串口服务器信息
        String serverIp = "127.0.0.1"; // 串口服务器IP
        int serverPort = 18888; // 串口服务器端口

        // 2. 构建帧数据（使用 FrameBuilder）
        byte[] headerPrefix = {0x00, 0x00, 0x00, 0x00}; // 帧头前4字节（根据实际协议定义）
        String data = "$HXDQ,1,1,0,0,0,0,0,*35"; // 实际业务数据
        boolean addCrLf = true; // 需要添加回车换行符（\r\n -> 0x0D 0x0A）

        byte[] frame = FrameBuilder.buildFrame(data, addCrLf);
        System.out.println("待发送的帧（十六进制）: " + FrameBuilder.bytesToHex(frame));

        // 3. 发送帧数据
        String result = TcpToSerialClient.sendFrame(serverIp, serverPort, frame);
        System.out.println("发送结果: " + result);
    }

    // 字节数组转十六进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString().trim();
    }
}
